package cn.mw.cmdb.entity;

import cn.mw.cmdb.param.ImportContextParam;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.microMonitorCommon.api.user.MwUserApi;
import cn.mw.microMonitorCommon.entity.cmdb.ModelExportDataInfoParam;
import cn.mw.microMonitorCommon.entity.cmdb.MwImportResultParam;
import cn.mw.microMonitorCommon.entity.userDTO.OrgDTO;
import com.alibaba.fastjson.JSONArray;
import com.google.common.base.Strings;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.entity.PropertyTypeNumerical.isNumeric;
import static cn.mw.cmdb.service.impl.InstanceViewImpl.*;
import static cn.mw.cmdb.util.ValConvertUtil.longValueConvert;
import static cn.mw.components.mongodb.entity.CriteriaOpsType.like;

public class PropertyTypeOrg extends PropertyType<PropertyTypeOrg, Object> {
    public static final String ID = "orgs";
    private static List<OrgDTO> finalList = new ArrayList<>();
    private static List<String> finalOrgNameList = new ArrayList<>();

    private static Map<String, Object> map = new HashMap<>();

    public PropertyTypeOrg() {
        setId(ID);
        setName("机构/部门");
        setSortNum(11);
    }

    @Override
    public Object tableHeaderTipInfo(PropertyTypeRef propertyTypeRef) {
        return "部门机构请使用全路径导入，例:总部/分公司/科技部,多个数据用“,”隔开";
    }

    @Override
    public Criteria doCriteria(CriteriaOpsType opsType, String name, Object value) {
        MwUserApi userApi = PropertyType.userApi;
        List<Long> orgIds = new ArrayList<>();
        if (like.equals(opsType) &&  !(value instanceof List)) {
            List<OrgDTO> orgsByOrgNames = userApi.getOrgsByOrgNames(Arrays.asList(strValueConvert(value)));
            if (!CollectionUtils.isEmpty(orgsByOrgNames)) {
                for (OrgDTO dto : orgsByOrgNames) {
                    orgIds.add(dto.getId());
                }
            }
            value = orgIds;
        }

        Criteria criteria = null;
        switch (opsType) {
            case is:
            case like:
                if (value instanceof List) {
                    criteria = new Criteria(name).elemMatch(new Criteria().elemMatch(new Criteria().in((List<?>) value)));
                }
                break;
            case in:
                if (value instanceof List) {
                    criteria = new Criteria(name).in(((List<?>) value));
                } else {
                    criteria = new Criteria(name).in(value);
                }
                break;
            case nin:
                if (value instanceof List) {
                    criteria = new Criteria(name).nin(((List<?>) value).toArray());
                } else {
                    criteria = new Criteria(name).nin(value);
                }
                break;
            case exist:
                criteria = new Criteria(name).exists((boolean) value);
                break;
            case elemMatch:
                criteria = new Criteria(name).elemMatch(new Criteria().in(JSONArray.parse(strValueConvert(value))));
                break;
            case elemMatchMore:
                criteria = new Criteria(name).elemMatch(new Criteria().elemMatch(new Criteria().in(JSONArray.parse(strValueConvert(value)))));
                break;
            case ne:
                criteria = new Criteria(name).ne(value);
        }
        return criteria;
    }

    @Override
    public CriteriaOpsType getDefaultCriteriaOpsType() {
        return CriteriaOpsType.in;
    }

    @Override
    public PropertyTypeOrg newObj() {
        return new PropertyTypeOrg();
    }

    @Override
    public void refresh() {
        finalList.clear();
        finalOrgNameList.clear();
    }


    @Override
    public Object convertValue(Object value) {
        if (value == null) {
            return null;
        }
        if (!isNumeric(value) && !(value instanceof List)) {
            List<OrgDTO> orgsByOrgNames = new ArrayList<>();
            MwUserApi userApi = PropertyType.userApi;
            List<List<Long>> idsList = new ArrayList<>();
            orgsByOrgNames = userApi.getAllOrg();
            setOrgIds(orgsByOrgNames, idsList, value);
            return idsList;
        } else {
            return value;
        }
    }

    public boolean tableHeaderInfo(Map ms, PropertyInfo propertyInfo, List<String> labelNames, List<String> labelId) throws Exception {
        //导出表头数据时，表头字段的id和名称不能同时重复
        if ((labelId != null && !labelId.contains(propertyInfo.getId())) && (labelNames != null && !labelNames.contains(ms.get(nameKey)))) {
            ms.put(typeKey, PropertyTypeUser.ID);
            List<String> orgNameList = new ArrayList<>();
            MwUserApi mwUserApi = PropertyType.userApi;
            List<OrgDTO> orgsByOrgNames = new ArrayList<>();
            if (CollectionUtils.isEmpty(finalOrgNameList)) {
                //调用公共接口，获取对应的信息
                orgsByOrgNames = mwUserApi.getAllOrg();
                if (!CollectionUtils.isEmpty(orgsByOrgNames)) {
                    Map<String, List<Long>> stringListMap = convertListToMap(orgsByOrgNames);
                    orgNameList = new ArrayList<>(stringListMap.keySet());
                    if (!CollectionUtils.isEmpty(orgNameList)) {
                        finalOrgNameList = orgNameList;
                    }
                }
            } else {
                orgNameList = finalOrgNameList;
            }
            labelId.add(propertyInfo.getId());
            ms.put(selectDataKey, orgNameList);
            return true;
        }
        return false;
    }


    @Override
    public Object getDataValue(ImportContextParam contextParam) {
        MwImportResultParam resultParam = new MwImportResultParam();
        String message = "";
        List<ModelExportDataInfoParam> list = contextParam.getListInfos();
        if (CollectionUtils.isEmpty(list)) {
            resultParam.setMessage("获取解析失败");
            return resultParam;
        }

        ModelExportDataInfoParam importParam = contextParam.getParam();
        //属性名称
        String tableName = importParam.getTableName();
        Object cellValue = importParam.getCellValue();
        Map<String, Object> matchMap = new HashMap<>();
        importCheckInfo(resultParam, contextParam, matchMap);
        if (Strings.isNullOrEmpty(strValueConvert(cellValue))) {
            return resultParam;
        }
        MwUserApi mwUserApi = contextParam.getMwUserApi();
        List<List<Long>> idsList = new ArrayList<>();
        List<OrgDTO> orgsByOrgNames = new ArrayList<>();
        //多个部门使用逗号分割“，”，多层级部门使用/分割
        if (CollectionUtils.isEmpty(finalList)) {
            //调用部门公共接口，获取所有的部门信息
            orgsByOrgNames = mwUserApi.getAllOrg();
            finalList = new ArrayList<>(orgsByOrgNames);
        }
        orgsByOrgNames = finalList;

        message = setOrgIds(orgsByOrgNames, idsList, cellValue);
        //根据部门信息获取部门Id
        resultParam.setMessage(message);
        resultParam.setCellValue(idsList);
        return resultParam;
    }

    public String setOrgIds(List<OrgDTO> orgsByOrgNames, List<List<Long>> idsList, Object value) {
        String message = "";
        Map<String, List<Long>> stringListMap = convertListToMap(orgsByOrgNames);
//        Map<String, Long> idByNameMap = orgsByOrgNames.stream().collect(Collectors.toMap(s -> s.getOrgName(), s -> s.getId(), (
//                value1, value2) -> {
//            return value2;
//        }));

        List<Long> allOrgIds = orgsByOrgNames.stream().map(s -> s.getId()).collect(Collectors.toList());


        String[] orgArr = strValueConvert(value).split(",");
        if (orgArr != null) {
            for (String orgNames : orgArr) {
                if (!Strings.isNullOrEmpty(orgNames)) {
//                    if (idByNameMap != null && idByNameMap.containsKey(orgNames)) {
//                        Long aLong = idByNameMap.get(orgNames);
//                        if (idByNameMap != null && idByNameMap.containsKey(orgNames)) {
//                        Long aLong = idByNameMap.get(orgNames);
//                        List<Long> parentIds = getParentIds(orgsByOrgNames, aLong);
//                        List<Long> disIds = parentIds.stream().filter(s -> allOrgIds.contains(s)).collect(Collectors.toList());
//                        disIds.add(aLong);
//                        idsList.add(disIds);
//                    }
                    if (stringListMap != null && stringListMap.containsKey(orgNames)) {
                        List<Long> ids = stringListMap.get(orgNames);
                        idsList.add(ids);
                    } else {
                        message += orgNames + "不存在";
                    }
                }
            }
        }
        return message;
    }


    /**
     * 获取该组织所有的pid
     */

    // 获取指定 OrgDto 的所有父级 ID 集合
    public static List<Long> getParentIds(List<OrgDTO> orgDtos, Long id) {
        List<Long> parentIds = new ArrayList<>();
        findParentIds(orgDtos, id, parentIds);
        //集合反序，最上层父节点排在最前面
        Collections.reverse(parentIds);
        return parentIds;
    }

    private static void findParentIds(List<OrgDTO> orgDtos, Long id, List<Long> parentIds) {
        Optional<OrgDTO> currentOrg = orgDtos.stream().filter(org -> org.getId().equals(id)).findFirst();
        if (currentOrg.isPresent() && currentOrg.get().getPid() != null) {
            parentIds.add(currentOrg.get().getPid());
            findParentIds(orgDtos, currentOrg.get().getPid(), parentIds);
        }
    }


    public static Map<String, List<Long>> convertListToMap(List<OrgDTO> list) {
        Map<Long, OrgDTO> idToOrgMap = new HashMap<>();
        Map<String, List<Long>> resultMap = new HashMap<>();

        // Build a map of id to OrgDto for quick lookup
        for (OrgDTO org : list) {
            idToOrgMap.put(org.getId(), org);
        }

        // Build the result map
        for (OrgDTO org : list) {
            List<String> namePath = new ArrayList<>();
            List<Long> idPath = new ArrayList<>();
            buildPath(org, idToOrgMap, namePath, idPath);
            String key = String.join("/", namePath);
            resultMap.put(key, idPath);
        }

        return resultMap;
    }

    private static void buildPath(OrgDTO org, Map<Long, OrgDTO> idToOrgMap, List<String> namePath, List<Long> idPath) {
        if (org.getPid() != 0 && idToOrgMap.containsKey(org.getPid())) {
            buildPath(idToOrgMap.get(org.getPid()), idToOrgMap, namePath, idPath);
        }
        namePath.add(org.getOrgName());
        idPath.add(org.getId());
    }


    /**
     * 导入模板 机构名称需要携带父节点名称
     * name1/name2/name3
     *
     * @param orgDtos
     * @param id
     * @return
     */
    public static Map<String, Object> getParentInfoMap(List<OrgDTO> orgDtos, Long id) {
        List<Long> parentIds = new ArrayList<>();
        List<String> parentNames = new ArrayList<>();
        findParentInfo(orgDtos, id, parentIds, parentNames);

        // 获取当前节点的信息
        Optional<OrgDTO> currentOrg = orgDtos.stream().filter(org -> org.getId().equals(id)).findFirst();
        if (currentOrg.isPresent()) {
            parentIds.add(currentOrg.get().getId());
            parentNames.add(currentOrg.get().getOrgName());
        }

        // 反转列表顺序
        Collections.reverse(parentIds);
        Collections.reverse(parentNames);

        // 构造结果 Map
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put(String.join("/", parentNames), StringUtils.collectionToCommaDelimitedString(parentIds));

        return resultMap;
    }

    private static void findParentInfo(List<OrgDTO> orgDtos, Long id, List<Long> parentIds, List<String> parentNames) {
        Optional<OrgDTO> currentOrg = orgDtos.stream().filter(org -> org.getId().equals(id)).findFirst();
        if (currentOrg.isPresent() && currentOrg.get().getPid() != null) {
            parentIds.add(currentOrg.get().getPid());
            parentNames.add(currentOrg.get().getOrgName());
            findParentInfo(orgDtos, currentOrg.get().getPid(), parentIds, parentNames);
        }
    }


    /**
     * 将部门node中的id转为名称显示
     *
     * @param idByNameMap
     * @return
     */
    private String getNameConvert(OrgDTO dto, Map<Long, String> idByNameMap) {
        String nodesStr = strValueConvert(dto.getNodes());
        if (Strings.isNullOrEmpty(nodesStr)) {
            nodesStr += strValueConvert(dto.getId());
        }
        String[] split = nodesStr.split(",");
        String nodeName = "";
        if (split != null) {
            for (String sp : split) {
                long id = longValueConvert(sp);
                if (idByNameMap != null && idByNameMap.containsKey(id)) {
                    String name = idByNameMap.get(id);
                    nodeName += name + "/";
                }
            }
        }
        if (nodeName.length() > 1) {
            nodeName = nodeName.substring(0, nodeName.length() - 1);
        }
        return nodeName;
    }


    /**
     * 将nodes转为List
     *
     * @return
     */
    private List<Long> doNodesByList(OrgDTO dto) {
        String nodesStr = strValueConvert(dto.getNodes());
        if (Strings.isNullOrEmpty(nodesStr)) {
            nodesStr += strValueConvert(dto.getId());
        }
        List<Long> ids = new ArrayList<>();
        String[] split = nodesStr.split(",");
        if (split != null) {
            for (String idStr : split) {
                long id = longValueConvert(idStr);
                ids.add(id);
            }
        }
        return ids;
    }
}
